package simulator.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.util.List;

import simulator.hardware.Processor;
import simulator.software.Process;
import simulator.software.ProcessState;
import simulator.software.ProcessorRunnable;
import simulator.software.scheduling.PriorityScheduler;

import javax.imageio.ImageIO;
import javax.swing.JComponent;

import simulator.Scenario;
import simulator.SchedulingScenario;

/**
 * Swing component for rendering the state and history of a process.
 * 
 * @author Kyle Loomis
 * 
 */
public class ProcessRenderer extends JComponent
{
   private static final long serialVersionUID = 1L;
   private static final Color defaultColor = new Color(100, 100, 100);
   private Scenario scenario = null;
   private Process process = null;
   private static Font normalFont = new Font("Arial", Font.PLAIN, 12);
   private static Font blockedFont = new Font("Arial", Font.ITALIC, 12);
   private static Font runningFont = new Font("Arial", Font.BOLD, 12);
   private Image runningImage = null;
   private Image blockedImage = null;
   private Image readyImage = null;
   private Image doneImage = null;

   /**
    * Default constructor.
    * 
    * @param scenario
    * @param process
    */
   public ProcessRenderer(Scenario scenario, Process process)
   {
      this.scenario = scenario;
      this.process = process;

      ImageLoader loader = new ImageLoader();
      runningImage = loader.load("running.png");
      blockedImage = loader.load("blocked.png");
      readyImage = loader.load("ready.png");
      doneImage = loader.load("done.png");

      /*
      try
      {
         
         runningImage = ImageIO.read(new File("images/running.png"));
         blockedImage = ImageIO.read(new File("images/blocked.png"));
         readyImage = ImageIO.read(new File("images/ready.png"));
         doneImage = ImageIO.read(new File("images/done.png"));
      }
      catch (IOException ioe)
      {
         ioe.printStackTrace();
      }*/
   }

   public Dimension getPreferredSize()
   {
      return new Dimension(1000, 30);
   }

   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);

      Graphics2D area = (Graphics2D) g;
      int paddingLeft = 10;

      area.setColor(defaultColor);

      String status = process.getStatusDescriptor();
      Image decal = null;

      if (process.getState() == ProcessState.BLOCKED)
      {
         g.setFont(blockedFont);
         decal = blockedImage;
      }
      else if (process.getState() == ProcessState.RUNNING)
      {
         g.setFont(runningFont);
         decal = runningImage;
      }
      else if (process.getState() == ProcessState.DONE)
      {
         g.setFont(blockedFont);
         decal = doneImage;
      }
      else
      {
         g.setFont(normalFont);
         decal = readyImage;
      }

      g.drawImage(decal, paddingLeft, 0, 72, 24, this);
      g.drawString(process.getName(), paddingLeft + 80, 10);
      g.drawString(status, paddingLeft + 80, 24);
      g.drawString("B: " + Double.toString(process.getBlockProbability()),
            paddingLeft + 180, 10);

      if (scenario.getComputer().getKernel().getScheduler() instanceof PriorityScheduler)
      {
         g.drawString("P: " + Integer.toString(process.getAdjustedPriority())
               + "/" + Integer.toString(process.getPriority()),
               paddingLeft + 180, 24);
      }

      Rectangle r = area.getClipBounds();

      if (r != null)
      {
         drawHistory(area.create(250, 0, 850, 40), process);
      }
   }

   public void drawHistory(Graphics g, ProcessorRunnable p)
   {
      Graphics2D area = (Graphics2D) g;
      int quantWidth = 4;
      SchedulingScenario sched = (SchedulingScenario) scenario;

      Processor processor = sched.getComputer().getProcessors().get(0);
      List<ProcessorRunnable> history = processor.getHistory();

      int start = scenario.getCurrentStep() - 180;
      int end = scenario.getCurrentStep();

      for (int step = start; step < end && step < history.size(); step++)
      {
         if (step >= 0 && history.get(step) == p)
         {
            area.setPaint(new GradientPaint(quantWidth * (step - start), 0,
                  new Color(255, 255, 255), quantWidth * (step - start)
                        + quantWidth, 16, new Color(192, 216, 234)));
            area.fillRect(quantWidth * (step - start), 0, quantWidth, 16);
            area.setPaint(new Color(190, 190, 240));
            area.drawRect(quantWidth * (step - start), 0, quantWidth, 16);
         }
         else
         {
            area.setColor(new Color(200, 200, 200));
            area.drawLine(quantWidth * (step - start), 8, quantWidth
                  * (step - start) + quantWidth, 8);
         }
      }
   }
}
